<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SpringBoot 内置的 20个高效工具类</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            min-height: 100vh;
        }
        
        /* 首字下沉效果 */
        .drop-cap::first-letter {
            float: left;
            font-size: 4rem;
            line-height: 3rem;
            padding-right: 0.5rem;
            margin-top: 0.5rem;
            font-weight: 700;
            color: #4f46e5;
            font-family: 'Noto Serif SC', serif;
        }
        
        /* 代码块美化 */
        pre {
            background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
            border-radius: 12px;
            padding: 1.5rem;
            overflow-x: auto;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
            position: relative;
        }
        
        pre::before {
            content: '';
            position: absolute;
            top: 10px;
            left: 15px;
            width: 12px;
            height: 12px;
            background: #ff5f56;
            border-radius: 50%;
            box-shadow: 20px 0 0 #ffbd2e, 40px 0 0 #27c93f;
        }
        
        code {
            color: #e2e8f0;
            font-family: 'Fira Code', monospace;
            font-size: 0.9rem;
            line-height: 1.6;
        }
        
        /* 卡片悬停效果 */
        .tool-card {
            transition: all 0.3s ease;
            background: rgba(255, 255, 255, 0.9);
            backdrop-filter: blur(10px);
        }
        
        .tool-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
            background: rgba(255, 255, 255, 0.95);
        }
        
        /* 标题装饰 */
        .section-title {
            position: relative;
            padding-left: 1.5rem;
        }
        
        .section-title::before {
            content: '';
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            width: 5px;
            height: 80%;
            background: linear-gradient(180deg, #4f46e5 0%, #7c3aed 100%);
            border-radius: 3px;
        }
        
        /* 引用样式 */
        .quote-box {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 2rem;
            border-radius: 16px;
            position: relative;
            overflow: hidden;
        }
        
        .quote-box::before {
            content: '"';
            position: absolute;
            top: -20px;
            left: 20px;
            font-size: 8rem;
            opacity: 0.1;
            font-family: 'Noto Serif SC', serif;
        }
        
        /* 数字标记 */
        .number-badge {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 2.5rem;
            height: 2.5rem;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 50%;
            font-weight: 700;
            margin-right: 1rem;
            flex-shrink: 0;
        }
        
        /* Mermaid 图表样式 */
        .mermaid {
            background: white;
            padding: 2rem;
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
        }
    </style>
</head>
<body>
    <!-- Hero 区域 -->
    <section class="relative overflow-hidden bg-gradient-to-br from-indigo-600 via-purple-600 to-pink-500 text-white">
        <div class="absolute inset-0 bg-black opacity-20"></div>
        <div class="relative container mx-auto px-6 py-24">
            <div class="max-w-4xl mx-auto text-center">
                <h1 class="text-5xl md:text-7xl font-bold mb-6 leading-tight">
                    别再重复造轮子！
                </h1>
                <p class="text-2xl md:text-3xl mb-8 font-light">
                    SpringBoot 内置的 <span class="font-bold text-yellow-300">20个高效工具类</span>
                </p>
                <div class="flex justify-center space-x-8 text-lg">
                    <div class="flex items-center">
                        <i class="fas fa-rocket mr-2"></i>
                        <span>轻量级</span>
                    </div>
                    <div class="flex items-center">
                        <i class="fas fa-bolt mr-2"></i>
                        <span>高性能</span>
                    </div>
                    <div class="flex items-center">
                        <i class="fas fa-link mr-2"></i>
                        <span>低耦合</span>
                    </div>
                </div>
            </div>
        </div>
        <div class="absolute bottom-0 left-0 right-0">
            <svg viewBox="0 0 1440 120" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M0 120L60 110C120 100 240 80 360 70C480 60 600 60 720 65C840 70 960 80 1080 85C1200 90 1320 90 1380 90L1440 90V120H1380C1320 120 1200 120 1080 120C960 120 840 120 720 120C600 120 480 120 360 120C240 120 120 120 60 120H0V120Z" fill="white"/>
            </svg>
        </div>
    </section>

    <!-- 主要内容区 -->
    <main class="container mx-auto px-6 py-12 max-w-6xl">
        <!-- 引言部分 -->
        <div class="mb-16">
            <div class="bg-white rounded-2xl shadow-xl p-8 md:p-12">
                <p class="text-lg leading-relaxed text-gray-700 drop-cap">
                    还在自己写工具类？你已经被SpringBoot抛弃了！很多人嘴上说"别重复造轮子"，结果还在项目里一遍遍写String工具、Bean拷贝、文件处理、反射操作……
                </p>
                <div class="mt-8 quote-box">
                    <p class="text-lg mb-2">有人说："用这些就像开了外挂。"</p>
                    <p class="text-lg mb-2">也有人说："太黑箱，宁愿自己写。"</p>
                    <p class="text-xl font-bold">你怎么看？</p>
                </div>
            </div>
        </div>

        <!-- 工具类思维导图 -->
        <div class="mb-16">
            <h2 class="text-3xl font-bold mb-8 text-center text-gray-800">SpringBoot 工具类全景图</h2>
            <div class="mermaid">
                graph TD
                    A[SpringBoot 内置工具类] --> B[数据处理]
                    A --> C[HTTP 请求]
                    A --> D[缓存 & 异步]
                    A --> E[校验 & 日志]
                    A --> F[测试 & 调试]
                    A --> G[其他实用工具]
                    
                    B --> B1[StringUtils]
                    B --> B2[ObjectUtils]
                    B --> B3[CollectionUtils]
                    
                    C --> C1[RestTemplate]
                    C --> C2[WebClient]
                    C --> C3[TestTemplate]
                    C --> C4[MockRestServiceServer]
                    
                    D --> D1[CacheManager]
                    D --> D2[@Async + TaskExecutor]
                    D --> D3[EventPublisher]
                    
                    E --> E1[Assert]
                    E --> E2[@Validated]
                    E --> E3[Logback/Log4j2]
                    
                    F --> F1[MockMvc]
                    F --> F2[OutputCapture]
                    F --> F3[TestPropertyValues]
                    F --> F4[SpringBootTest]
                    
                    G --> G1[BannerCustomizer]
                    G --> G2[Environment]
                    G --> G3[SpelExpressionParser]
                    
                    style A fill:#4f46e5,stroke:#333,stroke-width:3px,color:#fff
                    style B fill:#10b981,stroke:#333,stroke-width:2px,color:#fff
                    style C fill:#f59e0b,stroke:#333,stroke-width:2px,color:#fff
                    style D fill:#ef4444,stroke:#333,stroke-width:2px,color:#fff
                    style E fill:#8b5cf6,stroke:#333,stroke-width:2px,color:#fff
                    style F fill:#3b82f6,stroke:#333,stroke-width:2px,color:#fff
                    style G fill:#ec4899,stroke:#333,stroke-width:2px,color:#fff
            </div>
        </div>

        <!-- 数据处理部分 -->
        <section class="mb-16">
            <h2 class="text-4xl font-bold mb-8 text-gray-800 section-title flex items-center">
                <span class="number-badge">1</span>
                数据处理
            </h2>
            
            <div class="grid md:grid-cols-3 gap-6">
                <div class="tool-card rounded-xl p-6 shadow-lg">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-font text-3xl text-indigo-600 mr-3"></i>
                        <h3 class="text-2xl font-bold">StringUtils</h3>
                    </div>
                    <p class="text-gray-600 mb-4">Spring 提供的 StringUtils 相比 Apache Commons Lang 版本更加轻量，且与 Spring 生态完美集成。</p>
                    <pre><code>// 判断字符串是否为空
StringUtils.isEmpty(str); 

// 判断字符串是否有内容
StringUtils.hasText(str);

// 数组合并成字符串
StringUtils.arrayToCommaDelimitedString(arr);</code></pre>
                </div>

                <div class="tool-card rounded-xl p-6 shadow-lg">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-cube text-3xl text-purple-600 mr-3"></i>
                        <h3 class="text-2xl font-bold">ObjectUtils</h3>
                    </div>
                    <p class="text-gray-600 mb-4">处理对象判空和默认值时，不要再写 if-else 了：</p>
                    <pre><code>// 安全判空
ObjectUtils.isEmpty(obj);

// 获取第一个非空对象
ObjectUtils.firstNonNull(obj1, obj2, defaultValue);

// 空安全toString
ObjectUtils.nullSafeToString(obj);</code></pre>
                </div>

                <div class="tool-card rounded-xl p-6 shadow-lg">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-layer-group text-3xl text-pink-600 mr-3"></i>
                        <h3 class="text-2xl font-bold">CollectionUtils</h3>
                    </div>
                    <p class="text-gray-600 mb-4">Spring 的集合工具类让集合操作更加优雅：</p>
                    <pre><code>// 集合判空
CollectionUtils.isEmpty(collection);

// 查找第一个匹配元素
CollectionUtils.find(collection, predicate);

// 合并数组
CollectionUtils.mergeArrayIntoCollection(arr, collection);</code></pre>
                </div>
            </div>
        </section>

        <!-- HTTP 请求部分 -->
        <section class="mb-16">
            <h2 class="text-4xl font-bold mb-8 text-gray-800 section-title flex items-center">
                <span class="number-badge">2</span>
                HTTP 请求
            </h2>
            
            <div class="grid md:grid-cols-2 gap-6">
                <div class="tool-card rounded-xl p-6 shadow-lg">
                    <div class="flex items-center mb-4">
                        <i class="fas fa-exchange-alt text-3xl text-orange-600 mr-3"></i>
                        <h3 class="text-2xl font-bold">RestTemplate</h3>
                        <span class="ml-auto bg-yellow-100 text-yellow-800 px-3 py-1 rounded-full text-sm">传统同步</span>
                    </div>
                    <p class="text-gray-600 mb-4">虽然已被标记为过时，但在非响应式项目中依然实用：</p>
                    <pre><code>// 简单GET请求
String result = restTemplate.getForObject(url, String.class);

// 带参数的POST请求
ResponseEntity<String> response = restTemplate.postFor